#include "texture.h"
#define STB_IMAGE_IMPLEMENTATION
#include "../application/stb_image.h"

Texture::Texture(const std::string &path, unsigned int unit) {
  mUnit = unit;
  // 1. 读取图片
  // 1.1 反转y轴
  stbi_set_flip_vertically_on_load(true);
  // 2. 生成纹理并激活单元绑定
  glGenTextures(1, &mTexture);
  glActiveTexture(GL_TEXTURE0 + mUnit);
  glBindTexture(GL_TEXTURE_2D, mTexture);
  // 3. 传输纹理数据，开辟显存
  int channels;
  unsigned char *data =
      stbi_load(path.c_str(), &mWidth, &mHeight, &channels, STBI_rgb_alpha);
  /* glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_RGBA,
               GL_UNSIGNED_BYTE, data); */
  // 遍历每个mipmap的层级，为每个级别的mipmap填充图片数据
  int level = 0;
  int width = mWidth;
  int height = mHeight;

  while (true) {
    // 1. 将当前级别的mipmap对应的数据发往GPU端
    glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, data);
    //  2. 判断是否退出循环
    if (width <= 1 && height <= 1) {
      break;
    }
    // 3. 计算下次循环的宽度和高度
    width = width > 1 ? width / 2 : 1;
    height = height > 1 ? height / 2 : 1;
    level++;
  }
  // 4. 释放数据
  stbi_image_free(data);
  // 5. 设置纹理过滤方式
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
                  GL_LINEAR_MIPMAP_NEAREST);
  // 6. 设置纹理包裹方式
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}

Texture::~Texture() {
  if (mTexture != 0) {
    glDeleteTextures(1, &mTexture);
  }
}

void Texture::bind() {
  glActiveTexture(GL_TEXTURE0 + mUnit);
  glBindTexture(GL_TEXTURE_2D, mTexture);
}
